package com.hs.pre.search;

import static org.apache.solr.request.SolrParams.ROWS;
import static org.apache.solr.request.SolrParams.START;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.lucene.search.Query;
import org.apache.solr.core.Config;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrException;
import org.apache.solr.request.QueryResponseWriter;
import org.apache.solr.request.SolrParams;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.request.XMLWriter;
import org.apache.solr.search.DocListAndSet;
import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.servlet.SolrServletRequest;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.hs.common.JSONHandle;
import com.hs.core.action.BaseAction;
import com.hs.core.cache.OSCacheManager;
import com.hs.log.HsLogger;
import com.hs.pre.model.PreEntry;
import com.hs.utils.ParseXml;

public class SimSearchAction extends BaseAction{
	SolrCore core;
	private static final HsLogger logger = HsLogger.getLogger(SimSearchAction.class.getName());
	static String textUrl_ZZ = Config.getInstanceDir()
			+ "data/similars/PRES_FJ_ZZSim0.txt";
	static String textUrl_GX = Config.getInstanceDir()
			+ "data/similars/PRES_FJ_GXSim0.txt";
	static String textUrl_ZY = Config.getInstanceDir()
			+ "data/similars/PRES_FJ_ZYSim0.txt";
	static String textUrl_NAME = Config.getInstanceDir()
			+ "data/similars/PRES_FJ_NameSimFreq.txt";
	static int MAX_RETURN_NUM = 1000;
	

	public void init() throws ServletException {
		 core = SolrCore.getSolrCore();
		
	     logger.config("init"); 
	}
	
	/**
	 * get similar fjids  
	 * @param fjid original fjid
	 * @param type similar type---ZZ or NAME or YWZC or GX
	 * @param simDegree the minimum similarity degree to be satisfied
	 * @return a new query string
	 * @author CaoMudan on 2008-10-26
	 */
	private String getNewQ(String fjid,String simType,String simDegree){
		OSCacheManager oscache = OSCacheManager.getInstance();
		if("".equals(fjid)){
			return "";
		}
		String simTextUrl = "";		 
		if (simType.equals("ZZ")) {
			simTextUrl = textUrl_ZZ;
		} else if (simType.equals("MC")) {
			simTextUrl = textUrl_NAME;
		} else if (simType.equals("YWZC")) {
			simTextUrl = textUrl_ZY;
		} else if (simType.equals("GX")) {
			simTextUrl = textUrl_GX;
		} else {
			simTextUrl = textUrl_NAME;//default
		}
		
		String sim = "0.0";
		if (simDegree != null && !"".equals(simDegree)) {
			sim = simDegree;
			logger.info("sim degree is set to " + sim);
		}
		StringBuilder newQstr = new StringBuilder();
		try {
			long start = System.currentTimeMillis();
			FileInputStream in = null;
			BufferedReader reader = null;
//			if(oscache != null){
//				in = (FileInputStream)oscache.getObjectFromCacheByKey(simTextUrl);
//				System.out.println("read data from cache" + in);
//			}
//			if(null == in){ 
//			   in = new FileInputStream(simTextUrl);
//			   System.out.println("read data from file");
//			   oscache.putInCache(simTextUrl, in);
//			} 
			in = new FileInputStream(simTextUrl);
			reader = new BufferedReader(new InputStreamReader(
					in));
			String line = "";
			while ((line = reader.readLine()) != null) {
				String[] ids = line.split(":");
				if (ids.length == 2) {
					if (fjid.equals(ids[0].trim())) {
						//logger.info("====");
						if (simType.equals("MC")) {
							String[] simIds = ids[1].split(",");
							//logger.info("length:" + simIds.length);
							for (int i = 0; i < simIds.length; i++) {
								newQstr.append(simIds[i]);
								newQstr.append(" ");
							}
						} else {
							String[] simIds = ids[1].split(";");
							//logger.info("length:" + simIds.length);
							for (int i = 0; i < simIds.length; i++) {
								if (simIds[i].split(",")[1].compareTo(sim) >= 0) {
									newQstr.append(simIds[i].split(",")[0]);
									newQstr.append("^");
									newQstr.append(simIds[i].split(",")[1]);
									newQstr.append(" ");
								}
							}
						}
						break;
					}
				}
			}
			if (newQstr.length() > 1) {
				newQstr.delete(newQstr.length() - 1, newQstr.length());
			}
			if(reader != null)
			reader.close();
			long end = System.currentTimeMillis();
			logger.info("similar type:"+simType+" read time:" + (end - start) + " source id is " + fjid
					+ " new query string is " + newQstr.toString());
		} catch (FileNotFoundException ex) {
			logger.info("similarity file not found!");
		} catch (IOException ex) {
			logger.info("similarity file reader close error!");
		}
		return newQstr.toString();
	}
	
	/**
	 * mod by CaoMudan on 2008-10-27
	 */
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) throws Exception { 
		    String newQ=getNewQ(request.getParameter("q"),request.getParameter("type"),request.getParameter("sim"));		   
		    if(newQ==null || newQ.equals("")){
		    	return null;
		    }
		    
		    init();  
		    request.setCharacterEncoding("utf-8");
		    
		    SolrServletRequest solrReq = new SolrServletRequest(core, request);;
		    SolrQueryResponse solrRsp = new SolrQueryResponse();
		    
		    SolrParams p = solrReq.getParams();
		    String defaultField="id";
		    DocListAndSet results = new DocListAndSet();
		    Query query = QueryParsing.parseQuery(newQ, defaultField, p,
		    		solrReq.getSchema());
		    SolrIndexSearcher s = solrReq.getSearcher();
			results.docList = s.getDocList(query, null, null, p.getInt(START, 0), p
					.getInt(ROWS, MAX_RETURN_NUM), 0);
			logger.info(request.getParameter("type")+"--similarity result size:"+results.docList.size());
			solrRsp.add("similarRsp", results.docList);
			

		    try {
//		      SolrRequestHandler handler = core.getRequestHandler(solrReq.getQueryType());
//		      if (handler==null) {
//		    	  logger.warning("Unknown Request Handler '" + solrReq.getQueryType() +"' :" + solrReq);
//		        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,"Unknown Request Handler '" + solrReq.getQueryType() + "'", true);
//		      }
//		      
//		      core.execute(handler, solrReq, solrRsp );
//		      logger.info("original q:"+request.getParameter("q")+" solr req Q:"+solrReq.getParam("q"));
			
			
		      if (solrRsp.getException() == null) {
		        QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
		        StringWriter out = new StringWriter();        
		        XMLWriter.writeResponse(out,solrReq, solrRsp); 
		        
		        ParseXml parse = new ParseXml(out.getBuffer().toString());
		        List docList = parse.getDoc();
		        
		        List entryList = new ArrayList();
		        for(int i = 0;i<docList.size();i++){
		        	PreEntry entry = new PreEntry((Map)docList.get(i));
		        	entryList.add(entry);		        	
		        } 
		        JSONHandle jSONHandle= new JSONHandle();
		        
		        //to enable json Chinese format
		        response.setHeader("Cache-Control", "no-cache");
		        response.setContentType("text/json;charset=gb2312");

		        PrintWriter outStr = response.getWriter();
		        outStr.println(jSONHandle.getJsonToStr(entryList));
		       // logger.info(jSONHandle.getJsonToStr(entryList));
				out.flush();
				out.close();

		      } else {
		        Exception e = solrRsp.getException();
		        int rc=500;
		        if (e instanceof SolrException) {
		           rc=((SolrException)e).code();
		        }
		        sendErr(rc, SolrException.toStr(e), request, response);
		      }
		    } catch (SolrException e) {
		      if (!e.logged) logger.info(e.getMessage());
		      sendErr(e.code(), SolrException.toStr(e), request, response);
		    } 
//		    catch (Throwable e) {
//		    	logger.info(e.getMessage());
//		      sendErr(500, SolrException.toStr(e), request, response);
//		    } finally {
//		      // This releases the IndexReader associated with the request
//		      solrReq.close();
//		    }
		    		    
		return null;
	}
	 final void sendErr(int rc, String msg, HttpServletRequest request, HttpServletResponse response) {
		    try {
		      // hmmm, what if this was already set to text/xml?
		      try{
		        response.setContentType(QueryResponseWriter.CONTENT_TYPE_TEXT_UTF8);
		        // response.setCharacterEncoding("UTF-8");
		      } catch (Exception e) {}
		      try{response.setStatus(rc);} catch (Exception e) {}
		      PrintWriter writer = response.getWriter();
		      writer.write(msg);
		    } catch (IOException e) {
		       e.printStackTrace();
		    }
		  }
}
